home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / file-tra / fsp-2.7 / fsp-2 / fsp / server / host.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-23  |  9.9 KB  |  359 lines

  1.     /*********************************************************************\
  2.     *  Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu)   *
  3.     *                                                                     *
  4.     *  You may copy or modify this file in any manner you wish, provided  *
  5.     *  that this notice is always included, and that you hold the author  *
  6.     *  harmless for any loss or damage resulting from the installation or *
  7.     *  use of this software.                                              *
  8.     \*********************************************************************/
  9.  
  10. #include "tweak.h"
  11. #include "server_def.h"
  12. #include "s_extern.h"
  13. #include <ctype.h>
  14. #include <netdb.h>
  15.  
  16. /****************************************************************************
  17. * This file contains routines to maintain client database.
  18. ****************************************************************************/
  19.  
  20. #ifndef VMS
  21. extern char *realloc(), *malloc(), *ctime();
  22. #endif
  23. extern int priv_mode;
  24. extern int no_unnamed;
  25.  
  26. static HTAB     *htab;        /* client data base.            */
  27. static unsigned  hcnt;        /* number of clients.            */
  28. static unsigned  htot = 0;    /* available entries in the data base.    */
  29. static HTAB     hzero;
  30.  
  31. #define HALLOC_SIZE 30
  32.  
  33. IPrange **iptab = 0;
  34. unsigned int ipcnt = 0, iptot = 0;
  35.  
  36. char *check_ip PROTO1(unsigned long, inet_num)
  37. {
  38.   int i, j;
  39.   unsigned char val[4];
  40.   
  41.   val[0] = (inet_num & 0x000000ff)      ;
  42.   val[1] = (inet_num & 0x0000ff00) >>  8;
  43.   val[2] = (inet_num & 0x00ff0000) >> 16;
  44.   val[3] = (inet_num & 0xff000000) >> 24;
  45.   
  46.   for (i = 0; i < ipcnt; i++) {
  47.     for (j = 0; j < 4; j++)
  48.       if (iptab[i]->lo[j] > val[j] || val[j] > iptab[i]->hi[j]) break;
  49.     if (j == 4) break;
  50.   }
  51.   
  52.   if (i >= ipcnt) return 0;
  53.   
  54.   return iptab[i]->text;
  55. }
  56.  
  57. #define skip_whitespace(x) do {while (*(x)&&isspace(*(x))) (x)++;} while (0)
  58.  
  59. /* parse the text string as an integer and return a value between 0x00 and 0xff
  60.    if there is any error in forming the value (e.g., the text string
  61.    isn't an integer, or the integer value is too large) then make the
  62.    text string NULL */
  63. static unsigned char parse_ipcomponentnum PROTO1(char **, textp)
  64. {
  65.   unsigned long val = 0;
  66.   
  67.   if (!isdigit(**textp)) {
  68.     *textp = 0;
  69.   } else
  70.     do {
  71.       val = 10 * val + (**textp - '0');
  72.       (*textp)++;
  73.     } while (isdigit(**textp));
  74.   
  75.   if (val > 0xff) {
  76.     val = 0;
  77.     *textp = 0;
  78.   }
  79.   
  80.   return val;
  81. }
  82.  
  83. /* parse a whole field of a numerical IP address; it can be one of:
  84.    integer        >> fixed value
  85.    integer '-' integer    >> range of values
  86.    '*'            >> same as 0-255
  87.    */
  88. static char *parse_ipcomponent PROTO3(char *, text, unsigned char *, lo,
  89.                       unsigned char *, hi)
  90. {
  91.   if (*text == '*') {
  92.     *lo = 0x00;
  93.     *hi = 0xff;
  94.     return (text + 1);
  95.   }
  96.   
  97.   *lo = parse_ipcomponentnum(&text);
  98.   if (!text) return 0;
  99.   
  100.   if (*text == '-') {
  101.     text++;
  102.     *hi = parse_ipcomponentnum(&text);
  103.   } else *hi = *lo;
  104.   
  105.   return text;
  106. }
  107.  
  108. static IPrange *parse_ipnumber PROTO1(char *, text)
  109. {
  110.   IPrange *reply;
  111.   int i;
  112.   
  113.   reply = (IPrange *)malloc(sizeof(IPrange));
  114.   
  115.   for (i = 3; i >= 0 && !isspace(*text); i--) {
  116.     if (i < 3) {
  117.       if (*text != '.') return 0;
  118.       else text++;
  119.     }
  120.     text = parse_ipcomponent(text, &reply->lo[i], &reply->hi[i]);
  121.     if (!text) {
  122.       free((char *)reply);
  123.       return 0;
  124.     }
  125.   }
  126.   
  127.   /* fill in the gaps in the case that the loop terminated due to
  128.      the occurrence of white-space */
  129.   for (; i >= 0; i--) {
  130.     reply->lo[i] = 0x00;
  131.     reply->hi[i] = 0xff;
  132.   }
  133.   
  134.   return reply;
  135. }
  136.  
  137. static IPrange *parse_hostname PROTO2(char *, text, int, len)
  138. {
  139.   IPrange *reply;
  140.   struct hostent *hostaddr;
  141.   unsigned long inet_num;
  142.   char *hostname;
  143.   
  144.   hostname = malloc(len + 1);
  145.   strncpy(hostname, text, len);
  146.   hostname[len] = 0;
  147.   
  148.   hostaddr = gethostbyname(hostname);
  149.   free(hostname);
  150.   
  151.   if (!hostaddr) return 0;
  152.   
  153.   reply = (IPrange *)malloc(sizeof(IPrange));
  154.   inet_num = ((struct in_addr *)(hostaddr->h_addr))->s_addr;
  155.   reply->lo[0] = reply->hi[0] = (inet_num & 0x000000ff)      ;
  156.   reply->lo[1] = reply->hi[1] = (inet_num & 0x0000ff00) >>  8;
  157.   reply->lo[2] = reply->hi[2] = (inet_num & 0x00ff0000) >> 16;
  158.   reply->lo[3] = reply->hi[3] = (inet_num & 0xff000000) >> 24;
  159.   
  160.   return reply;
  161. }
  162.  
  163. /* parse a single line for the IP hosts file */
  164. IPrange *parse_ipline PROTO1(char *, text)
  165. {
  166.   IPrange *reply;
  167.   char type = 0;
  168.   char *message = 0;
  169.   int messlen = 0, addresslen;
  170.   
  171.   /* skip the leading white-space; if the line is commented or empty,
  172.      ignore it */
  173.   skip_whitespace(text); if (!*text || *text == '#') return 0;
  174.   
  175.   /* find the first non-space character after the address - this
  176.      identifies the type of host this is */
  177.   message = text;
  178.   while (*message && !isspace(*message)) message++;
  179.   addresslen = message - text;
  180.   skip_whitespace(message);
  181.   
  182.   if (!*message || *message == '#') {
  183.     /* if a host name is mentioned by itself, then treat it as ignored
  184.        or normal depending on the value of priv_mode */
  185.     type = priv_mode ? 'N': 'I';
  186.     message = "";
  187.     messlen = 0;
  188.   } else {
  189.     /* the first character after the host name is the type of host */
  190.     type = *message;
  191.     
  192.     /* skip over the white space trailing the type - the start of the
  193.        associated message */
  194.     message++; /* remember skip_whitespace() is a macro... */
  195.     skip_whitespace(message);
  196.     
  197.     /* `remove' the trailing white-space from the message */
  198.     messlen = strlen(message);
  199.     while (messlen > 0 && isspace(message[messlen-1])) messlen--;
  200.   }
  201.   
  202.   /* if the first character of the address is numerical or '*' then parse
  203.      as a numerical address, otherwise we do a host lookup on the name. */
  204.   if (*text == '*' || isdigit(*text))
  205.     reply = parse_ipnumber(text);
  206.   else
  207.     reply = parse_hostname(text, addresslen);
  208.   
  209.   if (!reply) {
  210.     fprintf(stderr, "Badly formed address in config file:\n\t%s", text);
  211.     return 0;
  212.   }
  213.   
  214.   /* allocate a string to hold the message */
  215.   reply->text = malloc(1 + messlen + 1); /* type + text + '\0' */
  216.   reply->text[0] = type;
  217.   strncpy(&reply->text[1], message, messlen);
  218.   reply->text[1 + messlen] = '\0';
  219.   
  220.   return reply;
  221. }
  222.  
  223. /****************************************************************************
  224.  * Write out the IP table in the .IPTAB_DUMP file.
  225.  ****************************************************************************/
  226.  
  227. int dump_iptab PROTO0((void))
  228. {
  229.   int i;
  230.   FILE *fp;
  231.   
  232.   if (!(fp = fopen(".IPTAB_DUMP","w"))) return;
  233.   
  234.   for (i = 0; i < ipcnt; i++) {
  235.     fprintf(fp, "%3d-%3d.%3d-%3d.%3d-%3d.%3d-%3d  %c  `%s'\n",
  236.         iptab[i]->lo[3], iptab[i]->hi[3],
  237.         iptab[i]->lo[2], iptab[i]->hi[2],
  238.         iptab[i]->lo[1], iptab[i]->hi[1],
  239.         iptab[i]->lo[0], iptab[i]->hi[0],
  240.         iptab[i]->text[0], &iptab[i]->text[1]);
  241.   }
  242.   
  243.   fclose(fp);
  244. }
  245.  
  246. /****************************************************************************
  247.  * Look up the hostname for an inet number.  Return NULL if not found.
  248.  ****************************************************************************/
  249.  
  250. static char *find_hostname PROTO1(unsigned long, inet_num)
  251. {
  252.   struct hostent *he;
  253.   char *hostname;
  254.   
  255.   if ((he = gethostbyaddr((char*)&inet_num, sizeof(inet_num), AF_INET))) {
  256.     hostname = malloc(strlen(he->h_name)+1);
  257.     strcpy(hostname, he->h_name);
  258.   } else
  259.     hostname = 0;
  260.   
  261.   return hostname;
  262. }
  263.  
  264. /****************************************************************************
  265.  * Returns an entry from the database corresponding to to the inet number.
  266.  * A new entry is created is it is not found.
  267.  * The database is a linear array of sorted structures.
  268.  * Entries are searched using binary search on the array.
  269.  ****************************************************************************/
  270.  
  271. HTAB *find_host PROTO1(unsigned long, inet_num)
  272. {
  273.   unsigned l, h, m, i;
  274.   unsigned long inum;
  275.   HTAB *hs, *hd;
  276.   
  277.   for(l = 0, h = hcnt-1; (m = (l + h) >> 1) != l; ) {    /* binary search */
  278.     inum = htab[m].inet_num;
  279.     if(inum > inet_num) h = m;
  280.     else if(inum < inet_num) l = m;
  281.     else {
  282.       /* if we *need* reverse naming and we haven't already got one
  283.      then try looking it up again. */
  284.       if (no_unnamed && !htab[m].hostname)
  285.     htab[m].hostname = find_hostname(inum);
  286.       htab[m].acc_cnt++;
  287.       return(htab+m);
  288.     }
  289.   }
  290.   
  291.   if(htab[m].inet_num < inet_num) m++;  /* locate first entry that is > */
  292.   
  293.   if((hcnt+1) > htot) { /* need more space */
  294.     htot += HALLOC_SIZE;        /* add HALLOC_SIZE entries at a time */
  295.     
  296.     if(!(htab = (HTAB *) realloc(htab,sizeof(HTAB)*htot))) {
  297.       perror("grow_htab realloc");
  298.       exit(1);
  299.     }
  300.   }
  301.   
  302.   for(i = hcnt-m, hs = htab+hcnt, hd=htab+hcnt+1; i--; *--hd = *--hs);
  303.   
  304.   htab[m]=hzero;
  305.   htab[m].inet_num = inet_num;
  306.   htab[m].last_key = get_next_key();
  307.   htab[m].next_key = get_next_key()+1;
  308.   htab[m].hostname = find_hostname(inet_num);
  309.   hcnt++;
  310.   return(htab+m);
  311. }
  312.  
  313. /****************************************************************************
  314.  * Client database initialization routine.
  315.  ****************************************************************************/
  316.  
  317. int init_htab PROTO0((void)) /* always have 2 entries -- 0, MAXINT */
  318. {
  319.   FILE *fp;
  320.   HTAB *hp;
  321.   char buf[1024];
  322.   unsigned int i1,i2,i3,i4;
  323.   unsigned long hnum;
  324.   
  325.   if(!(htab = (HTAB *) malloc(sizeof(HTAB)*HALLOC_SIZE))) {
  326.     perror("grow_htab malloc");
  327.     exit(1);
  328.   }
  329.   htab[0] = hzero;
  330.   htab[1] = hzero;
  331.   htab[1].inet_num = ~0;
  332.   hcnt = 2;
  333.   htot = HALLOC_SIZE;
  334. }
  335.  
  336. /****************************************************************************
  337.  * Write out the client table in the .HTAB_DUMP file.
  338.  ****************************************************************************/
  339.  
  340. int dump_htab PROTO0((void))
  341. {
  342.   int i;
  343.   FILE *fp;
  344.   HTAB *hp;
  345.   
  346.   if(!(fp = fopen(".HTAB_DUMP","w"))) return;
  347.   
  348.   for(i = hcnt-2, hp = htab+1; i--; hp++) {
  349.     fprintf(fp,"%d.%d.%d.%d\t%5d %s", ((unsigned char *)(&hp->inet_num))[0],
  350.         ((unsigned char *)(&hp->inet_num))[1],
  351.         ((unsigned char *)(&hp->inet_num))[2],
  352.         ((unsigned char *)(&hp->inet_num))[3],
  353.         hp->acc_cnt,
  354.         ctime((time_t *) &(hp->last_acc)));
  355.   }
  356.   
  357.   fclose(fp);
  358. }
  359.